package com.terra.ns.imp.common.dingtalk.service

import com.aliyun.dingtalkstorage_2_0.models.*
import com.aliyun.teautil.models.RuntimeOptions
import com.terra.ns.imp.common.dingtalk.client.DingtalkClient
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.io.File
import java.io.FileInputStream
import java.net.HttpURLConnection
import java.net.URL

/**
@author qins
@date 2023/9/20
@desc 钉盘文件操作
 */
@Service
class DingtalkFileService {

    @Autowired
    private lateinit var authService: DingAuthService

    @Autowired
    private lateinit var dingtalkClient: DingtalkClient

    /**
     * 上传文件到钉盘
     * https://developers.dingtalk.com/document/app/obtain-file-upload-informations
     */
    fun uploadFile(parentDentryUuid: String, unionId: String,  fileFullPath: String,  fileName: String, conflictStrategy: String): CommitFileResponseBody.CommitFileResponseBodyDentry {
        try {
            val token = authService.getAccessToken()
            // 获取上传文件信息
            val headers = GetFileUploadInfoHeaders().setXAcsDingtalkAccessToken(token)
            val request = GetFileUploadInfoRequest().setProtocol("HEADER_SIGNATURE").setUnionId(unionId)
            val uploadFileInfo = dingtalkClient.storageClient()
                .getFileUploadInfoWithOptions(parentDentryUuid, request, headers, RuntimeOptions()).body
            // 上传文件
            val url = URL(uploadFileInfo.headerSignatureInfo.resourceUrls[0])
            val conn = url.openConnection() as HttpURLConnection
            uploadFileInfo.headerSignatureInfo.headers.forEach {
                conn.setRequestProperty(it.key, it.value)
            }
            conn.doOutput = true
            conn.requestMethod = "PUT"
            conn.useCaches = false
            conn.readTimeout = 10000
            conn.connectTimeout = 10000
            conn.connect()
            val out = conn.outputStream
            val inputStream = FileInputStream(File(fileFullPath))
            val b = ByteArray(1024)
            var temp: Int
            while (inputStream.read(b).also { temp = it } != -1) {
                out.write(b, 0, temp)
            }
            out.flush()
            out.close()
            val responseCode = conn.responseCode
            conn.disconnect()
            if (responseCode == 200) {
                val commitFileHeaders = CommitFileHeaders().setXAcsDingtalkAccessToken(token)
                val commitFileRequest = CommitFileRequest()
                    .setUnionId(unionId)
                    .setUploadKey(uploadFileInfo.uploadKey)
                    .setName(fileName)
                    .setOption(
                        CommitFileRequest.CommitFileRequestOption()
                            .setConflictStrategy(conflictStrategy)
                        //                        .setAppProperties(
                        //                            listOf(CommitFileRequest.CommitFileRequestOptionAppProperties().setName("fieldKey").setValue("fieldValue").setVisibility("PUBLIC"))
                        //                        )
                    )
                val commitFileResponse = dingtalkClient.storageClient().commitFileWithOptions(
                    parentDentryUuid,
                    commitFileRequest,
                    commitFileHeaders,
                    RuntimeOptions()
                ).body
                return commitFileResponse.dentry

            } else {
                throw RuntimeException("上传文件至钉盘失败: ${conn.responseMessage}")
            }
        } catch (ex: Exception) {
            ex.printStackTrace()
            throw RuntimeException("文件上传失败: " + ex.message)
        }
    }
}